home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / game / shoot / ADescentSrc.lha / descent / Amiga / virge_fpu.c < prev    next >
C/C++ Source or Header  |  1998-04-09  |  19KB  |  723 lines

  1. #ifdef VIRGIN
  2. #include <math.h>
  3. #include <stdio.h>
  4. #include <utility/tagitem.h>
  5. #include <exec/exec.h>
  6. #include <proto/exec.h>
  7. #include <proto/utility.h>
  8. #include <proto/cybergraphics.h>
  9. #include <cybergraphics/cgx3dvirgin.h>
  10. #include <clib/cgx3dvirgin_protos.h>
  11. #include <inline/cgx3dvirgin.h>
  12. #include "virge.h"
  13. #include "texmap.h"
  14. #include "game.h"
  15.  
  16. extern APTR MyView;
  17. extern struct Library *CGX3DVirginBase;
  18. extern int VirgeFilter;
  19. extern int VirgeModulateLight;
  20.  
  21. V3DTriangle vtri;
  22.  
  23.  
  24. __inline vfloat vAddLight(vfloat component, int add)
  25. {
  26.     vfloat res;
  27.     if (add==0 || VirgeModulateLight==0) return component;
  28.     res = component + (vfloat)(add<<2);
  29.     if (res>255.0) res=255.0;
  30.     return res;
  31. }
  32.  
  33. void VirgeDrawPolyP(g3ds_tmap *tmap, const APTR texture)
  34. {
  35.     int ll;
  36.     int i;
  37.     vVertex v1,v2,v3;
  38.     vfloat x[10],y[10];//,iz[10];
  39.     vfloat u[10],v[10];
  40.     vfloat l[10];
  41.     int fl1 = 0;
  42.     int fl2 = 0;
  43.  
  44.     // --- Prepare values
  45.     for (i=0; i<tmap->nv; i++) {
  46.         x[i] =       (vfloat)tmap->verts[i].x2d / 65536.0;
  47.         y[i] =       (vfloat)tmap->verts[i].y2d / 65536.0;
  48.         //iz[i]= 4.0 * (vfloat)tmap->verts[i].z   / 65536.0;
  49.         u[i] =       (vfloat)((tmap->verts[i].u>>14)+256);
  50.         v[i] =       (vfloat)((tmap->verts[i].v>>14)+256);
  51.  
  52.         // --- Get and correct lighting level.
  53.         ll = tmap->verts[i].l>>8;
  54.         if (ll)         ll--;       // correct level
  55.         if (ll>0xff)    ll=0xff;    // and cut off
  56.         l[i] =          (vfloat)ll;
  57.     }
  58.  
  59.     for (i=0; i<tmap->nv; i++) {
  60.         if (u[i]<0) fl1=1;
  61.         if (v[i]<0) fl2=1;
  62.     }
  63.  
  64.     if (fl1) {
  65.         for (i=0; i<tmap->nv; i++) {
  66.             u[i] += 256.f;
  67.         }
  68.     }
  69.  
  70.     if (fl2) {
  71.         for (i=0; i<tmap->nv; i++) {
  72.             v[i] += 256.f;
  73.         }
  74.     }
  75.  
  76.     // --- Draw a triangle fan
  77.     //     Common Vertex 0 moved out from inner loop to save time
  78.     //     Move back for perspective correction (p.c. modifies
  79.     //     structure values).
  80.     v1.x = x[0]; v1.y = y[0]; //v1.iz = iz[0];
  81.     v1.u = u[0]; v1.v = v[0];
  82.     v1.r = vAddLight(l[0],PaletteRedAdd); v1.g = vAddLight(l[0], PaletteGreenAdd);
  83.     v1.b = vAddLight(l[0],PaletteBlueAdd);
  84.     if (V3D_LockView(MyView)) {
  85.         for (i=1; i<tmap->nv-1; i++) {
  86.  
  87.             // Draw a triangle 0 - i - i+1
  88.             v2.x = x[i]; v2.y = y[i]; //v2.iz = iz[i];
  89.             v2.u = u[i]; v2.v = v[i];
  90.             v2.r = vAddLight(l[i],PaletteRedAdd);
  91.             v2.g = vAddLight(l[i],PaletteGreenAdd);
  92.             v2.b = vAddLight(l[i],PaletteBlueAdd);
  93.  
  94.             v3.x = x[i+1]; v3.y = y[i+1]; //v3.iz = iz[i+1];
  95.             v3.u = u[i+1]; v3.v = v[i+1];
  96.             v3.r = vAddLight(l[i+1], PaletteRedAdd);
  97.             v3.g = vAddLight(l[i+1], PaletteGreenAdd);
  98.             v3.b = vAddLight(l[i+1], PaletteBlueAdd);
  99.             VirgeTriangle(texture, &v1, &v2, &v3);
  100.         }
  101.         V3D_UnLockView(MyView);
  102.     }
  103. }
  104.  
  105. void VirgeDrawPolyPP(g3ds_tmap *tmap, const APTR texture)
  106. {
  107.     int ll;
  108.     int i;
  109.     vVertex v1,v2,v3;
  110.     vfloat x[10],y[10],iz[10];
  111.     vfloat u[10],v[10];
  112.     vfloat l[10];
  113.     int fl1 = 0;
  114.     int fl2 = 0;
  115.  
  116.     // --- Prepare values
  117.     for (i=0; i<tmap->nv; i++) {
  118.         x[i] =       (vfloat)tmap->verts[i].x2d / 65536.0;
  119.         y[i] =       (vfloat)tmap->verts[i].y2d / 65536.0;
  120.         iz[i]= 4.0 * (vfloat)tmap->verts[i].z   / 65536.0;
  121.         u[i] =       (vfloat)((tmap->verts[i].u>>14)+256);
  122.         v[i] =       (vfloat)((tmap->verts[i].v>>14)+256);
  123.  
  124.         // --- Get and correct lighting level.
  125.         ll = tmap->verts[i].l>>8;
  126.         if (ll)         ll--;       // correct level
  127.         if (ll>0xff)    ll=0xff;    // and cut off
  128.         l[i] =          (vfloat)ll;
  129.     }
  130.  
  131.     for (i=0; i<tmap->nv; i++) {
  132.         if (u[i]<0) fl1=1;
  133.         if (v[i]<0) fl2=1;
  134.     }
  135.  
  136.     if (fl1) {
  137.         for (i=0; i<tmap->nv; i++) {
  138.             u[i] += 256.f;
  139.         }
  140.     }
  141.  
  142.     if (fl2) {
  143.         for (i=0; i<tmap->nv; i++) {
  144.             v[i] += 256.f;
  145.         }
  146.     }
  147.  
  148.     // --- Draw a triangle fan
  149.     //     Common Vertex 0 moved out from inner loop to save time
  150.     //     Move back for perspective correction (p.c. modifies
  151.     //     structure values).
  152.     if (V3D_LockView(MyView)) {
  153.         for (i=1; i<tmap->nv-1; i++) {
  154.             v1.x = x[0]; v1.y = y[0]; v1.iz = iz[0];
  155.             v1.u = u[0]; v1.v = v[0];
  156.             v1.r = vAddLight(l[0],PaletteRedAdd); v1.g = vAddLight(l[0], PaletteGreenAdd);
  157.             v1.b = vAddLight(l[0],PaletteBlueAdd);
  158.  
  159.             // Draw a triangle 0 - i - i+1
  160.             v2.x = x[i]; v2.y = y[i]; v2.iz = iz[i];
  161.             v2.u = u[i]; v2.v = v[i];
  162.             v2.r = vAddLight(l[i],PaletteRedAdd);
  163.             v2.g = vAddLight(l[i],PaletteGreenAdd);
  164.             v2.b = vAddLight(l[i],PaletteBlueAdd);
  165.  
  166.             v3.x = x[i+1]; v3.y = y[i+1]; v3.iz = iz[i+1];
  167.             v3.u = u[i+1]; v3.v = v[i+1];
  168.             v3.r = vAddLight(l[i+1], PaletteRedAdd);
  169.             v3.g = vAddLight(l[i+1], PaletteGreenAdd);
  170.             v3.b = vAddLight(l[i+1], PaletteBlueAdd);
  171.             VirgeTriangleP(texture, &v1, &v2, &v3);
  172.         }
  173.         V3D_UnLockView(MyView);
  174.     }
  175. }
  176.  
  177.  
  178. void VirgeTriangleP(const APTR texture, vVertex *p1, vVertex *p2, vVertex *p3)
  179. {
  180.     sdword y1, y2, y3, dy2, dy3;
  181.     vVertex *pe1top, *pe1bot, *pe2top, *pe2bot, *pTmp;
  182.     vfloat drdx, dgdx, dbdx, dudx, dvdx, den, dadx = 0;
  183.     vfloat e1idy, e2idy, e3idy, e1dxdy, e2dxdy, e3dxdy;
  184.     vfloat e1drdy, e1dgdy, e1dbdy, e1dudy, e1dvdy, e1dady = 0;
  185.     vfloat dwdx, e1dwdy;
  186.     vfloat r0, g0, b0, u0, v0, w0;
  187.     vfloat e1frac, e2frac, e3frac;
  188.     dword left_to_right, e2scans, e3scans;
  189.  
  190.         // ViRGE registers to write
  191.     dword dGdX_dBdX, dAdX_dRdX, dGdY_dBdY, dAdY_dRdY, GS_BS, AS_RS; // S8.7
  192.     dword dXdY12, Xend12, dXdY01, Xend01, dXdY02, XS;               // S11.20
  193.     dword YS, LR_Y01_Y12;               // LR (bit 31) == render left to right
  194.  
  195.     dword US, VS, dUdX, dVdX, dUdY, dVdY;
  196.  
  197.     dword dWdX, WS, dWdY;
  198.  
  199.     p1->iz *= 4.f;//096.f;
  200.     p2->iz *= 4.f;//096.f;
  201.     p3->iz *= 4.f;//096.f;
  202. //    printf("(%f %f %f) (%f %f)\n", p1->iz, p2->iz, p3->iz, p2->u, p2->v);
  203.  
  204.     p1->u = p1->u * p1->iz * 8.f;
  205.     p1->v = p1->v * p1->iz * 8.f;
  206.     p2->u = p2->u * p2->iz * 8.f;
  207.     p2->v = p2->v * p2->iz * 8.f;
  208.     p3->u = p3->u * p3->iz * 8.f;
  209.     p3->v = p3->v * p3->iz * 8.f;
  210.  
  211.     left_to_right = 0;
  212.  
  213.         // Find bottom-most pixel
  214.     y1 = floor(p1->y);
  215.     y2 = floor(p2->y);
  216.     y3 = floor(p3->y);
  217.  
  218.     if (y1 == y2 && y2 == y3)
  219.         return;
  220.  
  221.         // Calc global d?/dx
  222.     den = (p2->x - p1->x) * (p3->y - p1->y) - (p3->x - p1->x) * (p2->y - p1->y);
  223.     den = 1.0 / den;
  224.     drdx = ((p2->r - p1->r) * (p3->y - p1->y) - (p3->r - p1->r) * (p2->y - p1->y)) * den;
  225.     dgdx = ((p2->g - p1->g) * (p3->y - p1->y) - (p3->g - p1->g) * (p2->y - p1->y)) * den;
  226.     dbdx = ((p2->b - p1->b) * (p3->y - p1->y) - (p3->b - p1->b) * (p2->y - p1->y)) * den;
  227.     dudx = ((p2->u - p1->u) * (p3->y - p1->y) - (p3->u - p1->u) * (p2->y - p1->y)) * den;
  228.     dvdx = ((p2->v - p1->v) * (p3->y - p1->y) - (p3->v - p1->v) * (p2->y - p1->y)) * den;
  229.     dwdx = ((p2->iz - p1->iz) * (p3->y - p1->y) - (p3->iz - p1->iz) * (p2->y - p1->y)) * den;
  230.  
  231.         // Determine the topology
  232.     if (y1 > y2)
  233.     {
  234.         if (y1 > y3)
  235.         {
  236.             // p1 is bottom-most
  237.             // NO CHANGE
  238.         } else { // if (y3 > y1) {
  239.             // p3 is bottom most
  240.             pTmp = p1;
  241.             p1 = p3;
  242.             p3 = pTmp;
  243.             y1 ^= y3 ^= y1 ^= y3;
  244.         }
  245.     } else if (y2 > y1) {
  246.         if (y2 > y3)
  247.         {
  248.             // p2 is bottom-most
  249.             pTmp = p1;
  250.             p1 = p2;
  251.             p2 = pTmp;
  252.             y1 ^= y2 ^= y1 ^= y2;
  253.         } else {
  254.             // p3 is bottom most
  255.             pTmp = p1;
  256.             p1 = p3;
  257.             p3 = pTmp;
  258.             y1 ^= y3 ^= y1 ^= y3;
  259.         }
  260.     } else if (y3 > y1)
  261.     {
  262.         // p3 is bottom most
  263.         pTmp = p1;
  264.         p1 = p3;
  265.         p3 = pTmp;
  266.         y1 ^= y3 ^= y1 ^= y3;
  267.     }
  268.  
  269.         // p1 is bottommost now
  270.     dy2 = y1 - y2;
  271.     dy3 = y1 - y3;
  272.  
  273.     if (dy2 == 0)
  274.     {
  275.         pe1bot = p2;
  276.         pe1top = p3;
  277.         pe2bot = p1;
  278.         pe2top = p3;
  279.         if (pe1bot->x < pe2bot->x)
  280.             left_to_right = (1 << 31);
  281.         e2scans = dy3;
  282.         e3scans = 0;
  283.     }
  284.     else if (dy3 == 0)
  285.     {
  286.         pe1bot = p3;
  287.         pe1top = p2;
  288.         pe2bot = p1;
  289.         pe2top = p2;
  290.         if (pe1bot->x < pe2bot->x)
  291.             left_to_right = (1 << 31);
  292.         e2scans = dy2;
  293.         e3scans = 0;
  294.     } else {
  295.         if (dy2 > dy3)
  296.         {
  297.             pe1bot = p1;
  298.             pe1top = p2;
  299.             pe2bot = p1;
  300.             pe2top = p3;
  301.             e2scans = dy3;
  302.             e3scans = dy2 - dy3;
  303.         } else if (dy3 > dy2) {
  304.             pe1bot = p1;
  305.             pe1top = p3;
  306.             pe2bot = p1;
  307.             pe2top = p2;
  308.             e2scans = dy2;
  309.             e3scans = dy3 - dy2;
  310.         } else {
  311.             pe1bot = p1;
  312.             pe1top = p2;
  313.             pe2bot = p1;
  314.             pe2top = p3;
  315.             e2scans = dy2;
  316.             e3scans = 0;
  317.             if (pe1top->x < pe2top->x)
  318.                 left_to_right = (1 << 31);
  319.         }
  320.     }
  321.  
  322.         // Geometry calcs
  323.     e1idy = 1.0 / (pe1bot->y - pe1top->y);
  324.     e2idy = 1.0 / (pe2bot->y - pe2top->y);
  325.     e1dxdy = (pe1top->x - pe1bot->x) * e1idy;
  326.     e1drdy = (pe1top->r - pe1bot->r) * e1idy;
  327.     e1dgdy = (pe1top->g - pe1bot->g) * e1idy;
  328.     e1dbdy = (pe1top->b - pe1bot->b) * e1idy;
  329.     e1dudy = (pe1top->u - pe1bot->u) * e1idy;
  330.     e1dvdy = (pe1top->v - pe1bot->v) * e1idy;
  331.     e1dwdy = (pe1top->iz - pe1bot->iz) * e1idy;
  332.     e2dxdy = (pe2top->x - pe2bot->x) * e2idy;
  333.     e1frac = pe1bot->y - floor(pe1bot->y);
  334.     e2frac = pe2bot->y - floor(pe2bot->y);
  335.  
  336.     r0 = pe1bot->r + e1drdy * e1frac;
  337.     g0 = pe1bot->g + e1dgdy * e1frac;
  338.     b0 = pe1bot->b + e1dbdy * e1frac;
  339.     u0 = pe1bot->u + e1dudy * e1frac;
  340.     v0 = pe1bot->v + e1dvdy * e1frac;
  341.     w0 = pe1bot->iz + e1dwdy * e1frac;
  342.  
  343.     if (e3scans)
  344.     {
  345.         if (e2dxdy > e1dxdy)
  346.         {
  347.             left_to_right = (1 << 31);
  348.         }
  349.         e3idy = 1.0 / (pe2top->y - pe1top->y);
  350.         e3dxdy = (pe1top->x - pe2top->x) * e3idy;
  351.         e3frac = pe2top->y - floor(pe2top->y);
  352.     }
  353.  
  354.     if (!left_to_right)
  355.     {
  356.         drdx = -drdx;
  357.         dgdx = -dgdx;
  358.         dbdx = -dbdx;
  359.         dudx = -dudx;
  360.         dvdx = -dvdx;
  361.         dwdx = -dwdx;
  362.     }
  363.  
  364.  
  365.         // Prepare values for the ViRGE regs
  366.     XS          = (dword) ((pe1bot->x + e1frac * e1dxdy) * TWO_E_20);
  367.     Xend01      = (dword) ((pe2bot->x + e2frac * e2dxdy) * TWO_E_20);
  368.  
  369.     dXdY01      = (dword) (e2dxdy * TWO_E_20);
  370.     dXdY02      = (dword) (e1dxdy * TWO_E_20);
  371.  
  372.     if (e3scans)
  373.     {
  374.         dXdY12  = e3dxdy * TWO_E_20;
  375.         Xend12  = (dword) ((pe2top->x + e3frac * e3dxdy) * TWO_E_20);
  376.     }
  377.  
  378.     YS          = y1;
  379.     LR_Y01_Y12  = left_to_right | (e2scans << 16) | e3scans;
  380.  
  381.     dGdX_dBdX = (((dword)(dgdx * 128.0)) << 16)
  382.               | (((dword)(dbdx * 128.0)) & 0xFFFF);
  383.     dAdX_dRdX = (((dword)(dadx * 128.0)) << 16)
  384.               | (((dword)(drdx * 128.0)) & 0xFFFF);
  385.     dGdY_dBdY = (((dword)(e1dgdy * 128.0)) << 16)
  386.               | (((dword)(e1dbdy * 128.0)) & 0xFFFF);
  387.     dAdY_dRdY = (((dword)(e1dady * 128.0)) << 16)
  388.               | (((dword)(e1drdy * 128.0)) & 0xFFFF);
  389.  
  390.     GS_BS = (((sdword)(g0 * 128.0)) << 16)
  391.           | ((sdword)(b0 * 128.0));
  392.     AS_RS = (((sdword)(0 * 128.0)) << 16)
  393.           | ((sdword)(r0 * 128.0));
  394.  
  395.     US   = (sdword)(u0 * 128.0 * 1.0);
  396.     VS   = (sdword)(v0 * 128.0 * 1.0);
  397.     dUdX = (sdword)(dudx * 128.0 * 1.0);
  398.     dVdX = (sdword)(dvdx * 128.0 * 1.0);
  399.     dUdY = (sdword)(e1dudy * 128.0 * 1.0);
  400.     dVdY = (sdword)(e1dvdy * 128.0 * 1.0);
  401.  
  402.     WS = (sdword)(w0 * 256.0 * 2048.0);
  403.     dWdX =  (sdword)(dwdx * 256.0 * 2048.0);
  404.     dWdY = (sdword)(e1dwdy * 256.0 * 2048.0);
  405.  
  406.         // Do!
  407.  
  408.     bzero(&vtri, sizeof(vtri));
  409.     vtri.T3D_TdWdX = dWdX;
  410.     vtri.T3D_TdWdY = dWdY;
  411.     vtri.T3D_TWS   = WS;
  412.     vtri.T3D_TdDdX = 0x5;
  413.     vtri.T3D_TdVdX = dVdX;
  414.     vtri.T3D_TdUdX = dUdX;
  415.     vtri.T3D_TdDdY = 0x5;
  416.     vtri.T3D_TdVdY = dVdY;
  417.     vtri.T3D_TdUdY = dUdY;
  418.     vtri.T3D_TDS = 0x5;
  419.     vtri.T3D_TVS = VS;
  420.     vtri.T3D_TUS = US;
  421.  
  422.     vtri.T3D_TdGdX_dBdX = dGdX_dBdX;
  423.     vtri.T3D_TdAdX_dRdX = dAdX_dRdX;
  424.     vtri.T3D_TdGdY_dBdY = dGdY_dBdY;
  425.     vtri.T3D_TdAdY_dRdY = dAdY_dRdY;
  426.     vtri.T3D_TGS_BS = GS_BS;
  427.     vtri.T3D_TAS_RS = AS_RS;
  428.  
  429.     if (e3scans)
  430.     {
  431.         vtri.T3D_TdXdY12 = dXdY12;
  432.         vtri.T3D_TXEND12 = Xend12;
  433.     }
  434.     vtri.T3D_TdXdY01 = dXdY01;
  435.     vtri.T3D_TXEND01 = Xend01;
  436.     vtri.T3D_TdXdY02 = dXdY02;
  437.     vtri.T3D_TXS = XS;
  438.     vtri.T3D_TYS = YS;
  439.     vtri.T3D_TY01_Y12 = LR_Y01_Y12;
  440.  
  441.     vtri.T3D_CMD_SET =
  442.                   VIRGE_CS_3D
  443.                 | VIRGE_CS_CMD_LITTEXTRI_P
  444.                 | VIRGE_CS_BLEND_MODULATE
  445.                 | VIRGE_CS_TEXTURE_WRAP
  446.                 | ((6<<VIRGE_CS_MIPMAP_SIZE_POS) & VIRGE_CS_MIPMAP_SIZE_MSK)
  447.                 | VIRGE_CS_TEXFMT_16_1555
  448.                 | VIRGE_CS_HWCLIP
  449.                 ;
  450.     if (VirgeFilter == 1)
  451.         vtri.T3D_CMD_SET |= VIRGE_CS_TEXFILT_4TPP;
  452.      else
  453.         vtri.T3D_CMD_SET |= VIRGE_CS_TEXFILT_1TPP;
  454.  
  455.     V3D_BlitV3DTriangle(MyView, &vtri, texture);
  456. }
  457.  
  458.  
  459. #define o(x)
  460.     //printf("%s=%f\n", #x, x)
  461. #define o1(x)
  462.     //printf("%s=0x%X\n", #x, x)
  463.  
  464. void VirgeTriangle(const APTR texture, vVertex *p1, vVertex *p2, vVertex *p3)
  465. {
  466.     sdword y1, y2, y3, dy2, dy3;
  467.     vVertex *pe1top, *pe1bot, *pe2top, *pe2bot, *pTmp;
  468.     vfloat drdx, dgdx, dbdx, dudx, dvdx, den, dadx = 0;
  469.     vfloat e1idy, e2idy, e3idy, e1dxdy, e2dxdy, e3dxdy;
  470.     vfloat e1drdy, e1dgdy, e1dbdy, e1dudy, e1dvdy, e1dady = 0;
  471.     vfloat r0, g0, b0, u0, v0;
  472.     vfloat e1frac, e2frac, e3frac;
  473.     dword left_to_right, e2scans, e3scans;
  474.     static V3DTriangle vtri;
  475.  
  476.         // ViRGE registers to write
  477.     dword dGdX_dBdX, dAdX_dRdX, dGdY_dBdY, dAdY_dRdY, GS_BS, AS_RS; // S8.7
  478.     dword dXdY12, Xend12, dXdY01, Xend01, dXdY02, XS;               // S11.20
  479.     dword YS, LR_Y01_Y12;               // LR (bit 31) == render left to right
  480.  
  481.     dword US, VS, dUdX, dVdX, dUdY, dVdY;
  482.  
  483.  
  484.     left_to_right = 0;
  485.  
  486.         // Find bottom-most pixel
  487.     y1 = floor(p1->y);
  488.     y2 = floor(p2->y);
  489.     y3 = floor(p3->y);
  490.  
  491.     if (y1 == y2 && y2 == y3)
  492.         return;
  493.  
  494.         // Calc global d?/dx
  495.     den = (p2->x - p1->x) * (p3->y - p1->y) - (p3->x - p1->x) * (p2->y - p1->y);
  496.     den = 1.0 / den;
  497.     drdx = ((p2->r - p1->r) * (p3->y - p1->y) - (p3->r - p1->r) * (p2->y - p1->y)) * den;
  498.     dgdx = ((p2->g - p1->g) * (p3->y - p1->y) - (p3->g - p1->g) * (p2->y - p1->y)) * den;
  499.     dbdx = ((p2->b - p1->b) * (p3->y - p1->y) - (p3->b - p1->b) * (p2->y - p1->y)) * den;
  500.     dudx = ((p2->u - p1->u) * (p3->y - p1->y) - (p3->u - p1->u) * (p2->y - p1->y)) * den;
  501.     dvdx = ((p2->v - p1->v) * (p3->y - p1->y) - (p3->v - p1->v) * (p2->y - p1->y)) * den;
  502.     o(drdx); o(dgdx); o(dbdx); o(dudx); o(dvdx);
  503.  
  504.         // Determine the topology
  505.     if (y1 > y2)
  506.     {
  507.         if (y1 > y3)
  508.         {
  509.             // p1 is bottom-most
  510.             // NO CHANGE
  511.         } else { // if (y3 > y1)
  512.             // p3 is bottom most
  513.             pTmp = p1;
  514.             p1 = p3;
  515.             p3 = pTmp;
  516.             y1 ^= y3 ^= y1 ^= y3;
  517.         }
  518.     } else if (y2 > y1) {
  519.         if (y2 > y3)
  520.         {
  521.             // p2 is bottom-most
  522.             pTmp = p1;
  523.             p1 = p2;
  524.             p2 = pTmp;
  525.             y1 ^= y2 ^= y1 ^= y2;
  526.         } else {
  527.             // p3 is bottom most
  528.             pTmp = p1;
  529.             p1 = p3;
  530.             p3 = pTmp;
  531.             y1 ^= y3 ^= y1 ^= y3;
  532.         }
  533.     } else if (y3 > y1)
  534.     {
  535.         // p3 is bottom most
  536.         pTmp = p1;
  537.         p1 = p3;
  538.         p3 = pTmp;
  539.         y1 ^= y3 ^= y1 ^= y3;
  540.     }
  541.  
  542.         // p1 is bottommost now
  543.     dy2 = y1 - y2;
  544.     dy3 = y1 - y3;
  545.  
  546.     if (dy2 == 0)
  547.     {
  548.         pe1bot = p2;
  549.         pe1top = p3;
  550.         pe2bot = p1;
  551.         pe2top = p3;
  552.         if (pe1bot->x < pe2bot->x)
  553.             left_to_right = (1 << 31);
  554.         e2scans = dy3;
  555.         e3scans = 0;
  556.     }
  557.     else if (dy3 == 0)
  558.     {
  559.         pe1bot = p3;
  560.         pe1top = p2;
  561.         pe2bot = p1;
  562.         pe2top = p2;
  563.         if (pe1bot->x < pe2bot->x)
  564.             left_to_right = (1 << 31);
  565.         e2scans = dy2;
  566.         e3scans = 0;
  567.     } else {
  568.         if (dy2 > dy3)
  569.         {
  570.             pe1bot = p1;
  571.             pe1top = p2;
  572.             pe2bot = p1;
  573.             pe2top = p3;
  574.             e2scans = dy3;
  575.             e3scans = dy2 - dy3;
  576.         } else if (dy3 > dy2) {
  577.             pe1bot = p1;
  578.             pe1top = p3;
  579.             pe2bot = p1;
  580.             pe2top = p2;
  581.             e2scans = dy2;
  582.             e3scans = dy3 - dy2;
  583.         } else {
  584.             pe1bot = p1;
  585.             pe1top = p2;
  586.             pe2bot = p1;
  587.             pe2top = p3;
  588.             e2scans = dy2;
  589.             e3scans = 0;
  590.             if (pe1top->x < pe2top->x)
  591.                 left_to_right = (1 << 31);
  592.         }
  593.     }
  594.  
  595.         // Geometry calcs
  596.     e1idy = 1.0 / (pe1bot->y - pe1top->y);
  597.     e2idy = 1.0 / (pe2bot->y - pe2top->y);
  598.     e1dxdy = (pe1top->x - pe1bot->x) * e1idy;
  599.     e1drdy = (pe1top->r - pe1bot->r) * e1idy;
  600.     e1dgdy = (pe1top->g - pe1bot->g) * e1idy;
  601.     e1dbdy = (pe1top->b - pe1bot->b) * e1idy;
  602.     e1dudy = (pe1top->u - pe1bot->u) * e1idy;
  603.     e1dvdy = (pe1top->v - pe1bot->v) * e1idy;
  604.     e2dxdy = (pe2top->x - pe2bot->x) * e2idy;
  605.     e1frac = pe1bot->y - floor(pe1bot->y);
  606.     e2frac = pe2bot->y - floor(pe2bot->y);
  607.  
  608.     r0 = pe1bot->r + e1drdy * e1frac;
  609.     g0 = pe1bot->g + e1dgdy * e1frac;
  610.     b0 = pe1bot->b + e1dbdy * e1frac;
  611.     u0 = pe1bot->u + e1dudy * e1frac;
  612.     v0 = pe1bot->v + e1dvdy * e1frac;
  613.  
  614.     if (e3scans)
  615.     {
  616.         if (e2dxdy > e1dxdy)
  617.         {
  618.             left_to_right = (1 << 31);
  619.         }
  620.         e3idy = 1.0 / (pe2top->y - pe1top->y);
  621.         e3dxdy = (pe1top->x - pe2top->x) * e3idy;
  622.         e3frac = pe2top->y - floor(pe2top->y);
  623.     }
  624.  
  625.     if (!left_to_right)
  626.     {
  627.         drdx = -drdx;
  628.         dgdx = -dgdx;
  629.         dbdx = -dbdx;
  630.         dudx = -dudx;
  631.         dvdx = -dvdx;
  632.     }
  633.  
  634.  
  635.         // Prepare values for the ViRGE regs
  636.     XS          = (dword) ((pe1bot->x + e1frac * e1dxdy) * TWO_E_20);
  637.     Xend01      = (dword) ((pe2bot->x + e2frac * e2dxdy) * TWO_E_20);
  638.  
  639.     dXdY01      = (dword) (e2dxdy * TWO_E_20);
  640.     dXdY02      = (dword) (e1dxdy * TWO_E_20);
  641.  
  642.     if (e3scans)
  643.     {
  644.         dXdY12  = e3dxdy * TWO_E_20;
  645.         Xend12  = (dword) ((pe2top->x + e3frac * e3dxdy) * TWO_E_20);
  646.     }
  647.  
  648.     YS          = y1;
  649.     LR_Y01_Y12  = left_to_right | (e2scans << 16) | e3scans;
  650.  
  651.     dGdX_dBdX = (((dword)(dgdx * 128.0)) << 16)
  652.               | (((dword)(dbdx * 128.0)) & 0xFFFF);
  653.     dAdX_dRdX = (((dword)(dadx * 128.0)) << 16)
  654.               | (((dword)(drdx * 128.0)) & 0xFFFF);
  655.     dGdY_dBdY = (((dword)(e1dgdy * 128.0)) << 16)
  656.               | (((dword)(e1dbdy * 128.0)) & 0xFFFF);
  657.     dAdY_dRdY = (((dword)(e1dady * 128.0)) << 16)
  658.               | (((dword)(e1drdy * 128.0)) & 0xFFFF);
  659.  
  660.     GS_BS = (((sdword)(g0 * 128.0)) << 16)
  661.           | ((sdword)(b0 * 128.0));
  662.     AS_RS = (((sdword)(0 * 128.0)) << 16)
  663.           | ((sdword)(r0 * 128.0));
  664.  
  665.     US = (sdword)(u0 * 256.0 * 2048.0);
  666.     VS = (sdword)(v0 * 256.0 * 2048.0);
  667.     dUdX = (sdword)(dudx * 256.0 * 2048.0);
  668.     dVdX = (sdword)(dvdx * 256.0 * 2048.0);
  669.     dUdY = (sdword)(e1dudy * 256.0 * 2048.0);
  670.     dVdY = (sdword)(e1dvdy * 256.0 * 2048.0);
  671.  
  672.  
  673.     bzero(&vtri, sizeof(vtri));
  674.     vtri.T3D_TdDdX = 0;
  675.     vtri.T3D_TdVdX = dVdX;              o1(dVdX);                     
  676.     vtri.T3D_TdUdX = dUdX;              o1(dUdX);                     
  677.     vtri.T3D_TdDdY = 0;                                               
  678.     vtri.T3D_TdVdY = dVdY;              o1(dVdY);                     
  679.     vtri.T3D_TdUdY = dUdY;              o1(dUdY);                     
  680.     vtri.T3D_TDS = 0;                                                 
  681.     vtri.T3D_TVS = VS;                  o1(VS);                       
  682.     vtri.T3D_TUS = US;                  o1(US);                       
  683.                                                                       
  684.     vtri.T3D_TdGdX_dBdX = dGdX_dBdX;    o1(dGdX_dBdX);                
  685.     vtri.T3D_TdAdX_dRdX = dAdX_dRdX;    o1(dAdX_dRdX);                
  686.     vtri.T3D_TdGdY_dBdY = dGdY_dBdY;    o1(dGdY_dBdY);                
  687.     vtri.T3D_TdAdY_dRdY = dAdY_dRdY;    o1(dAdY_dRdY);                
  688.     vtri.T3D_TGS_BS = GS_BS;            o1(GS_BS);                    
  689.     vtri.T3D_TAS_RS = AS_RS;            o1(AS_RS);                    
  690.                                                                       
  691.     if (e3scans)                                                      
  692.     {                                                                 
  693.         vtri.T3D_TdXdY12 = dXdY12;      o1(dXdY12);                   
  694.         vtri.T3D_TXEND12 = Xend12;      o1(Xend12);                   
  695.     }                                                                 
  696.     vtri.T3D_TdXdY01 = dXdY01;          o1(dXdY01);                   
  697.     vtri.T3D_TXEND01 = Xend01;          o1(Xend01);                   
  698.     vtri.T3D_TdXdY02 = dXdY02;          o1(dXdY02);                   
  699.     vtri.T3D_TXS = XS;                  o1(XS);                       
  700.     vtri.T3D_TYS = YS;                  o1(YS);                       
  701.     vtri.T3D_TY01_Y12 = LR_Y01_Y12;     o1(LR_Y01_Y12);               
  702.  
  703.     vtri.T3D_CMD_SET =
  704.                   VIRGE_CS_3D
  705.                 | VIRGE_CS_CMD_LITTEXTRI
  706.                 | VIRGE_CS_BLEND_MODULATE
  707.                 | VIRGE_CS_TEXTURE_WRAP
  708.                 | ((6<<VIRGE_CS_MIPMAP_SIZE_POS) & VIRGE_CS_MIPMAP_SIZE_MSK)
  709.                 | VIRGE_CS_TEXFMT_16_1555
  710.                 | VIRGE_CS_HWCLIP
  711.                 ;
  712.     if (VirgeFilter == 1)
  713.         vtri.T3D_CMD_SET |= VIRGE_CS_TEXFILT_4TPP;
  714.      else
  715.         vtri.T3D_CMD_SET |= VIRGE_CS_TEXFILT_1TPP;
  716.  
  717.  
  718.     V3D_BlitV3DTriangle(MyView, &vtri, texture);
  719. }
  720.  
  721.  
  722. #endif
  723.